import {AbstractControl, ValidatorFn} from '@angular/forms';

export type CustomType = 'number' | '';
export type CaptchaType = 'img' | 'mobile';

/**
 * 自定义表单校验都是静态方法,直接引用即可,如果需要用在动态表单内 那么第一个参数必须为接受form,生成动态表单的基本数据
 */

export class CustomValidators {

    public static decimalPlaces({key, label}, length): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } => {
            if (control.value) {
                if (this.checkDecimalPlaces(control.value, length)) {
                    return null;
                } else {
                    return {key: {value: control.value, errorMsg: `${label}小数位数最多为${length}位`}};
                }
            } else {
                return null;
            }
        };
    }

    private static isNumber(val) {
        const regPos = /^\d+(\.\d+)?$/;  // 非负浮点数
        const regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; // 负浮点数
        return regPos.test(val) || regNeg.test(val);
    }


    static checkType(target, type): boolean {
        if (type) {
            switch (type) {
                case 'number':
                    return this.isNumber(target);
                default:
                    return true;
            }
        } else {
            return true;
        }
    }

    public static checkTypes({key, label}, type): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } => {
            if (control.value) {
                if (this.checkType(control.value, type)) {
                    return null;
                } else {
                    return {key: {value: control.value, errorMsg: `${label}必须为数字`}};
                }
            } else {
                return null;
            }
        };
    }

    public static captchaValidator(type: CaptchaType): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } => {
            if (control.value) {
                if (type === 'img' && control.value.length === 4) {
                    return null;
                } else if (type === 'mobile' && control.value.length === 6) {
                    return null;
                } else {
                    return {'captcha': {value: control.value, errorMsg: '验证码长度不对'}};
                }
            } else {
                return null; // 如果没有值传入 不管
            }
        };
    }

    public static phoneNumberValidator(): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } => {
            if (control.value) {
                if (this.checkPhone(control.value)) {
                    return null;
                } else {
                    return {'phoneNumber': {value: control.value, errorMsg: '请输入正确格式的手机号码'}};
                }
            } else {
                return null;
            }
        };
    }

    public static passwordValidator(): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } => {
            if (control.value && control.value.trim()) {
                if (/^(?![a-zA-Z]+$)(?![a-z\d]+$)(?![a-z!@#\$%]+$)(?![A-Z\d]+$)(?![A-Z!@#\$%]+$)(?![\d!@#\$%]+$)[a-zA-Z\d!@#\$%]{8,16}$/.test(control.value)) {
                    return null;
                } else {
                    return {
                        'password': {
                            value: control.value,
                            errorMsg: '请输入正确格式的密码，密码由8-16位数字、小写字母、大写字母或特殊字符中三种或四种组成'
                        }
                    };
                }
            } else {
                return {'password': {value: control.value, errorMsg: '请输入正确格式的密码，密码由8-16位数字、小写字母、大写字母或特殊字符中三种或四种组成'}};
            }
        };
    }

    public static equalToValidator({key, label}, value): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } => {
            if (value.value) {
                if (value.value === control.value) {
                    return null;
                } else {
                    return {key: {value: control.value, errorMsg: `${label}两次输入不一致`}};
                }
            } else {
                return null;
            }
        };
    }

    public static rangeLengthValidator(min: number, max: number): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } => {
            if (control.value) {
                const countCode = this.countCode(control.value);
                if (countCode >= min && countCode <= max) {
                    return null;
                } else {
                    return {'rangeLength': {value: control.value, errorMsg: `不能大于${max}个字符或${max / 2}个汉字`}};
                }
            } else {
                return null;
            }
        };
    }

    private static countCode(str: string): Number {
        let count = 0;
        for (let i = 0; i < str.length; i++) {
            const c = str.charCodeAt(i);
            if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
                count++;
            } else {
                count += 2;
            }
        }
        return count;
    }

    public static checkPhone(phoneNumber: string): Boolean {
        return /^1[34578]\d{9}$/.test(phoneNumber);
    }

    private static checkDecimalPlaces(value: string, length): Boolean {
        if (Number(length) === 0) { // 如果此方法传入的length为0,那么说明不校验此项目
            return true;
        } else {
            if (String(value).indexOf('.') !== -1) {
                const target = String(value).split('.');
                const targetLength = target[1].length;
                return targetLength <= Number(length);
            } else {
                return true;
            }
        }
    }

}




